#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//申请新链表节点
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* pnew = (SLTNode*)malloc(sizeof(SLTNode));
	if (pnew == NULL)
	{
		perror("申请节点失败");
		exit(1);
	}
	pnew->data = x;
	pnew->next = NULL;
	return pnew;
}
//寻找链表尾端的前一个结点（因为是传值调用所以不会影响原本头节点的值）
SLTNode** FindTailFront(SLTNode** pphead)
{
    //因为这个函数肯定是在别的函数里被引用的，能进行到这里pphead肯定不为空，就没加断言
	while ((*pphead)->next->next)
	{
		pphead = &((*pphead)->next);
	}
	return pphead;
}
//尾部插入
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* pnew = SLTBuyNode(x);
	if (*pphead && (*pphead)->next)//非单节点链表，需要找尾
	{
		pphead = FindTailFront(pphead);
		(*pphead)->next->next = pnew;
	}
	else if(*pphead==NULL)//空链表，直接赋值
	{
		(*pphead) = pnew;
	}
	else//单节点链表，给next赋值
	{
		(*pphead)->next = pnew;
	}
}
//头部插入
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* pnew = SLTBuyNode(x);
	pnew->next = *pphead;
	*pphead = pnew;
}
//尾部删除
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead && *pphead);//空链表不应该应用此方法
	if (*pphead && (*pphead)->next)//多节点链表
	{
		pphead = FindTailFront(pphead);
		free((*pphead)->next->next);
		(*pphead)->next = NULL;
	}
	else//单节点链表
	{
		free((*pphead)->next);
		*pphead = NULL;
	}
}
//头部删除
void SLTPopFront(SLTNode** pphead)
{
    assert(pphead && *pphead);//空链表不应该应用此方法
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead && *pphead && pos);//本来想的是这个函数是搭配SLTFind使用的，传来的pos非空那肯定不是空链表，但姑且还是加上对*pphead的断言吧
	SLTNode* pcur = *pphead;
	SLTNode* new = SLTBuyNode(x);
	if (pcur == pos)//这里就相当于是头插了
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		while (pcur->next != pos)
		{
			pcur = pcur->next;
		}
		pcur->next = new;
		new->next = pos;
	}
}
//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && pos);
	SLTNode* pcur = *pphead;
	if (pcur == pos)//此时相当于头删
	{
		SLTPopFront(pphead);
	}
	else
	{
		while (pcur->next != pos)
		{
			pcur = pcur->next;
		}
		SLTNode* next = pos->next;
		pcur->next = next;
		free(pos);
	}
}
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* next = pos->next;
	SLTNode* new = SLTBuyNode(x);
	pos->next = new;
	new->next = next;
}
//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
	SLTNode* next = pos->next;
	if (next)
	{
		pos->next = next->next;
		free(next);
	}
	else
	{
		printf("此位置之后已没有节点\n");
	}
}
//销毁链表
void SListDesTroy(SLTNode** pphead)
{
	assert(pphead);
    while (*pphead)//空链表根本不会进循环，函数不起任何作用，所以断言的时候就不把*pphead也丢进去，判断它是不是空链表了
    {
        assert(pphead);
        SLTNode* next = (*pphead)->next;
        free(*pphead);
        *pphead = next;
    }
}